package com.kch.web.controller.portal;

import com.alibaba.fastjson.JSON;
import com.kch.common.core.domain.AjaxResult;
import com.kch.framework.shiro.service.SysPasswordService;
import com.kch.framework.util.ShiroUtils;
import com.kch.system.domain.SysUser;
import com.kch.system.domain.WechatUser;
import com.kch.system.mapper.SysUserMapper;
import com.kch.system.mapper.WechatUserMapper;
import com.kch.system.wechat.WeChatInfoVO;
import com.kch.system.wechat.WechatLogin;
import com.kch.system.wechat.WechatResp;
import com.kch.web.config.WeChatProperties;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.Date;

@Controller
@RequestMapping("/wechat")
@Api(tags = "微信小程序登录")
@ResponseBody
public class WechatController {

    private static final Logger log = LoggerFactory.getLogger(WechatController.class);
    @Autowired
    private WeChatProperties weChatProperties;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysPasswordService passwordService;
    @Autowired
    private WechatUserMapper wechatUserMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @ApiOperation("微信登录")
    @PostMapping("/login")
    public AjaxResult wechatLogin(@RequestBody WechatLogin wechatLogin) {
        StringBuilder url = new StringBuilder("https://api.weixin.qq.com/sns/jscode2session?");
        url.append("appid=");//appid设置
        url.append(weChatProperties.getAppid());
        url.append("&secret=");//secret设置
        url.append(weChatProperties.getSecret());
        url.append("&js_code=");//code设置
        url.append(wechatLogin.getCode());
        url.append("&grant_type=authorization_code");
        log.info("传入code是:" + wechatLogin.getCode());
        log.info("请求连接:" + url.toString());
        String resp = restTemplate.getForObject(url.toString(), String.class);
        log.info("请求微信返回值:" + resp);
        WechatResp wechatResp = JSON.parseObject(resp, WechatResp.class);
        log.info("转换为对象值:" + wechatResp.toString());

       /* WeChatInfoVO weChatInfo = getUserInfo(wechatLogin.getEncryptedData(), body.getSession_key(), wechatLogin.getIv());
        if (ObjectUtils.isEmpty(weChatInfo)) {
            AjaxResult.error("解析用户信息失败");

        }*/
        //插入t_user表,wechat_user表,并返回微信用户信息
        SysUser user;
        log.info("转换为对象openId:" + wechatResp.getOpenid());
        WechatUser exist = wechatUserMapper.selectByOpenId(wechatResp.getOpenid());
        if(ObjectUtils.isEmpty(exist)){
            user = new SysUser();
            user.setLoginName("微信用户" + wechatResp.getOpenid());
            user.setUserName("微信用户");
            user.setPassword(weChatProperties.getPwd());
            user.setSalt(ShiroUtils.randomSalt());
            user.setUserType("11");
            user.setStatus("0");
            user.setDelFlag("0");
            user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
            user.setCreateBy("wechat");
            user.setCreateTime(new Date());
            user.setRemark("微信用户");
            sysUserMapper.insertUser(user);

            WechatUser wechatUser = new WechatUser();
            wechatUser.setOpenId(wechatResp.getOpenid());
            wechatUser.setUserId(user.getUserId().intValue());
            wechatUser.setCreateTime(new Date());
            wechatUserMapper.insert(wechatUser);
        }else{
            user = sysUserMapper.selectUserById(exist.getUserId().longValue());
        }

        UsernamePasswordToken token = new UsernamePasswordToken(user.getLoginName(), weChatProperties.getPwd(), true);
        Subject subject = SecurityUtils.getSubject();
        subject.login(token);
        return AjaxResult.success();
    }


    public static WeChatInfoVO getUserInfo(String encryptedData, String sessionKey, String iv) {
        byte[] dataByte = Base64.decode(encryptedData);
        byte[] keyByte = Base64.decode(sessionKey);
        byte[] ivByte = Base64.decode(iv);
        try {
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSON.parseObject(result, WeChatInfoVO.class);
            }
        } catch (Exception e) {
            log.error("解析加密参数有误");
        }
        return null;
    }
}
